/*Author: Rony Lahav (ID:043489889)*/

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.LinkedList;


/**
 * This class provides a user interface to the configuration file.
 * It reads the data from the file, parses it and then is ready to provide it to the user
 */
public class ConfigFileManager {
	static ConfigFileManager instance;	// Singleton instance
	static String dataSection;
	static String commandSection;
	static final String dataHeader="DATA";
	static final String commandHeader="COMMAND";
	final static String TYPE_AT = "AT";
	final static String TYPE_IM = "IM";
	final static String TYPE_FT = "FT";
	final static String TYPE_IDLE = "IDLE";
	final static String TYPE_FILTER = "FILTER";
	final static String TYPE_ID = "ID";
	final static String TYPE_UDP = "UDP";
	final static String TYPE_FREQ = "FREQUENCY";
	final static String TYPE_TIMEOUT = "TIMEOUT";
	final static String TYPE_PEER = "PEER";
	final static String TYPE_SN = "ISSUPERNODE";
	
	
	
	//singleton CTOR - reads the config file into String
	private ConfigFileManager() {
		try{
			LineNumberReader reader = new LineNumberReader(new FileReader(final_project.configFilePath));
			
			StringBuilder sb = new StringBuilder();
			
			String line = reader.readLine();
			while (line != null) {
				sb.append(line);
				sb.append(MessageCenter.newline);
				line = reader.readLine();
			}
			
			int dataIndex = sb.indexOf(dataHeader);
			int commandIndex = sb.indexOf(commandHeader);
			
			dataSection=sb.toString().substring(dataIndex, commandIndex);
			commandSection=sb.toString().substring(commandIndex);
		}
		catch (IOException e) {
			instance = null;
		}
	}
	
	//singleton
	public static ConfigFileManager getInstance() {
		if (instance==null)
			instance = new ConfigFileManager();
		return instance;
	}
	
	//parses the data section, initializes my DBTuple, frequancy+timeout and creates DBTuples for the Peers
	public DBTuple processDataSection(){
		DBTuple myTuple = new DBTuple();
		boolean error=false;
		String[] splittedData = dataSection.split(MessageCenter.newline);
		for (int i=0;i<splittedData.length;++i){
			if (splittedData[i].startsWith(TYPE_ID)){
				myTuple.setPeerID(splittedData[i].split(": ")[1]);
			}
			else if (splittedData[i].startsWith(TYPE_SN)){
				boolean val = Integer.parseInt(splittedData[i].split(": ")[1]) == 1;
				myTuple.setIsSN(val);
				final_project.getInstance().amIanSN = val;				
			}
			else if (splittedData[i].startsWith(TYPE_UDP)){
				myTuple.setUdpPort(splittedData[i].split(": ")[1]);
			}
			else if (splittedData[i].startsWith(TYPE_FREQ)){
				final_project.getInstance().frequency=Integer.parseInt(splittedData[i].split(": ")[1]);
			}
			else if (splittedData[i].startsWith(TYPE_TIMEOUT)){
				final_project.getInstance().timeout=Integer.parseInt(splittedData[i].split(": ")[1]);
			}
			else if (splittedData[i].startsWith(TYPE_PEER)){
				String peerData = splittedData[i].split(": ")[1];
				String[] peerIPPort = peerData.split(",");
				DBTuple newPeer = new DBTuple();
				newPeer.setPeerIP(peerIPPort[0]);
				newPeer.setUdpPort(peerIPPort[1]);
				newPeer.setStatus("0");
				newPeer.setIsSN(final_project.getInstance().amIanSN);
				newPeer.setLastConnectionTime(System.currentTimeMillis());
				if (final_project.getInstance().amIanSN)	//if i'm an SN all my records are SNs
					DataBase.getInstance().insertSN(newPeer);
				else
					DataBase.getInstance().insertTuple(newPeer);
			}
		}
		myTuple.setStatus("1");
		myTuple.setLastConnectionTime(System.currentTimeMillis());
		InetAddress addr;	//set my IP address
		try {
			addr = InetAddress.getLocalHost();
		    myTuple.setPeerIP(addr.getHostAddress());
		} catch (UnknownHostException e) {
			Logger.getInstance().printErrorMessage("ERROR - Network Details", null, myTuple.getPeerID(), null);
			error=true;
		}
		if (!error)
			return myTuple;
		else
			return null;
	}
	
	//parses the commands and returns all of them as a list of commands by creating the relevant command class for each of them
	public LinkedList<ICmd> getCommands() throws IOException {
		LinkedList<ICmd> commands = new LinkedList<ICmd>();
		String[] splittedCMDs = commandSection.split(MessageCenter.newline);
		for (int i=0;i<splittedCMDs.length;++i){
			if (splittedCMDs[i].startsWith(TYPE_AT)){
				commands.add(new CmdAT(splittedCMDs[i].split(": ")[1]));
			}
			else if (splittedCMDs[i].startsWith(TYPE_FILTER)){
				commands.add(new CmdFilter(splittedCMDs[i].split(": ")[1]));
			}
			else if (splittedCMDs[i].startsWith(TYPE_FT)){
				commands.add(new CmdFT(splittedCMDs[i].split(": ")[1]));
			}
			else if (splittedCMDs[i].startsWith(TYPE_IDLE)){
				commands.add(new CmdIdle(splittedCMDs[i].split(": ")[1]));
			}
			else if (splittedCMDs[i].startsWith(TYPE_IM)){
				commands.add(new CmdIM(splittedCMDs[i].split(": ")[1]));
			}
		}
		return commands;
	}
}
